package org.mybatis.generator.plugin.ext;

import org.mybatis.generator.api.*;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.exception.ShellException;
import org.mybatis.generator.file.GenerateByTemplateFile;
import org.mybatis.generator.formatter.FreemarkerTemplateFormatter;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.mybatis.generator.internal.ObjectFactory;
import org.mybatis.generator.internal.util.StringUtility;

import java.io.*;
import java.net.URL;
import java.util.*;

/**
 * Controller生成插件
 */
public class ControllerGeneratorPlugin extends PluginAdapter {

    /**
     * 默认的模板格式化类
     */
    public static final String DEFAULT_TEMPLATEFORMATTER = "org.mybatis.generator.formatter.FreemarkerTemplateFormatter";
    /**
     * 项目路径（目录需要已经存在）
     */
    private String targetProject;
    /**
     * 生成的包（路径不存在则创建）
     */
    private String targetPackage;

    /**
     * service类所在的包
     */
    private String servicePackage;

    /**
     * 模板路径
     */
    private String templatePath;
    /**
     * 模板内容
     */
    private String templateContent;
    /**
     * 模板生成器
     */
    private FreemarkerTemplateFormatter templateFormatter;

    private String templateFormatterClass;

    /**
     * 编码
     */
    private String encoding;

    private ShellCallback shellCallback = null;

    public ControllerGeneratorPlugin(){
        shellCallback = new DefaultShellCallback(false);
    }

    @Override
    public boolean validate(List<String> warnings) {
        boolean right = true;
        if (!StringUtility.stringHasValue(templatePath)) {
            warnings.add("没有配置 \"templatePath\" 模板路径，因此不会生成任何额外代码!");
            right = false;
        } else {
            try {
                URL resourceUrl = null;
                try {
                    resourceUrl = ObjectFactory.getResource(templatePath);
                } catch (Exception e) {
                    warnings.add("本地加载\"templatePath\" 模板路径失败，尝试 URL 方式获取!");
                }
                if (resourceUrl == null) {
                    resourceUrl = new URL(templatePath);
                }
                InputStream inputStream = resourceUrl.openConnection().getInputStream();
                templateContent = read(inputStream);//获取模板内容
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
                warnings.add("读取模板文件出错: " + e.getMessage());
                right = false;
            }
        }
        if (!StringUtility.stringHasValue(templateFormatterClass)) {
            templateFormatterClass = DEFAULT_TEMPLATEFORMATTER;
            warnings.add("没有配置 \"templateFormatterClass\" 模板处理器，使用默认的处理器!");
        }
        try {
            //templateFormatter = Class.forName(templateFormatterClass).newInstance();
            templateFormatter = new FreemarkerTemplateFormatter();
        } catch (Exception e) {
            warnings.add("初始化 templateFormatter 出错:" + e.getMessage());
            right = false;
        }
        if (!right) {
            return false;
        }
        int errorCount = 0;
        if (!StringUtility.stringHasValue(targetProject)) {
            errorCount++;
            warnings.add("没有配置 \"targetProject\" 路径!");
        }
        if (!StringUtility.stringHasValue(targetPackage)) {
            errorCount++;
            warnings.add("没有配置 \"targetPackage\" 路径!");
        }
        if (errorCount >= 2) {
            warnings.add("由于没有配置任何有效路径，不会生成任何额外代码!");
            return false;
        }
        return true;
    }

    /**
     * 读取文件
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    protected String read(InputStream inputStream) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, encoding));
        StringBuffer stringBuffer = new StringBuffer();
        String line = reader.readLine();
        while (line != null) {
            stringBuffer.append(line).append("\n");
            line = reader.readLine();
        }
        return stringBuffer.toString();
    }

    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        System.out.println("ControllerGeneratorPlugin→contextGenerateAdditionalJavaFiles");
        List<GeneratedJavaFile> list = new ArrayList<>();
        for (GeneratedJavaFile javaFile : introspectedTable.getGeneratedJavaFiles()) {
            String pkName = "";//主键名称
            String pkType = null;
            List<IntrospectedColumn> primaryKeyColumns = introspectedTable.getPrimaryKeyColumns();
            if (primaryKeyColumns.isEmpty()) {
                pkType = new FullyQualifiedJavaType("java.lang.String").getShortName();
                pkName="id";
            } else {
                StringBuffer sbPkType = new StringBuffer();
                StringBuffer sbPkName = new StringBuffer();
                for (IntrospectedColumn introspectedColumn : introspectedTable.getPrimaryKeyColumns()) {
                    sbPkType.append(introspectedColumn.getFullyQualifiedJavaType().getShortName());
                    sbPkType.append(" ");
                    sbPkType.append(introspectedColumn.getJavaProperty());
                    sbPkType.append(",");

                    sbPkName.append(introspectedColumn.getJavaProperty());
                    sbPkName.append(",");
                }
                if(sbPkName.length()>0){
                    sbPkName.setLength(sbPkName.length() - 1);//截取最后一个逗号
                }
                if(sbPkType.length()>0){
                    sbPkType.setLength(sbPkType.length() - 1);//截取最后一个逗号
                }
                pkType = sbPkType.toString();
                pkName = sbPkName.toString();
            }
            CompilationUnit unit = javaFile.getCompilationUnit();
            FullyQualifiedJavaType javaType = unit.getType();
            String shortName = javaType.getShortName();
            if (shortName.endsWith("Example") || shortName.endsWith("Mapper")) {// 针对Example类和Mapper类不要生成Controller
                continue;
            }
            String fileName = shortName+"Controller.java";
            String serviceName = toLowerCaseFirstOne(shortName);
            String modelClass = javaType.getFullyQualifiedName();
            String serviceClass = servicePackage+"."+shortName+"Service";
            try {
                File controllerFileDir = shellCallback.getDirectory(targetProject, targetPackage);
                File controllerFile = new File(controllerFileDir, fileName);
                if (!controllerFile.exists()) { // 文件不存在就生成
                    Map<String, Object> templateParams = new HashMap<>();
                    templateParams.put("targetPackage",this.targetPackage);
                    templateParams.put("requestMapping",toLowerCaseFirstOne(shortName));
                    templateParams.put("className",shortName);
                    templateParams.put("serviceName",serviceName);
                    templateParams.put("modelClass",modelClass);
                    templateParams.put("serviceClass",serviceClass);
                    templateParams.put("pkName",pkName);
                    templateParams.put("pkType",pkType);
                    list.add(new GenerateByTemplateFile(shortName, templateFormatter, properties, targetProject, targetPackage, templateContent,templateParams,fileName));
                }
            } catch (ShellException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    @Override
    public void setProperties(Properties properties) {
        super.setProperties(properties);
        this.targetProject = properties.getProperty("targetProject");
        this.targetPackage = properties.getProperty("targetPackage");
        this.servicePackage = properties.getProperty("servicePackage");
        this.templatePath = properties.getProperty("templatePath");
        this.encoding = properties.getProperty("encoding", "UTF-8");
    }

    //首字母转小写
    private String toLowerCaseFirstOne(String s){
        if(Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }


    //首字母转大写
    private String toUpperCaseFirstOne(String s){
        if(Character.isUpperCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
    }
}
